package com.xiaoniu.lib_keleim

import android.content.Context
import com.xiaoniu.lib_keleim.db.ConversationListCallBack
import com.xiaoniu.lib_keleim.db.MessageCountCallBack
import com.xiaoniu.lib_keleim.db.MessageListCallBack
import com.xiaoniu.lib_keleim.db.manager.MessageDao
import com.xiaoniu.lib_keleim.pojo.dos.UserEntity
import com.xiaoniu.lib_keleim.pojo.vos.AckMessage
import com.xiaoniu.lib_keleim.pojo.vos.BaseMessage
import com.xiaoniu.lib_keleim.pojo.vos.PreSendMessage
import com.xiaoniu.lib_keleim.pojo.vos.WrapperMessage
import com.xiaoniu.lib_keleim.spi.*
import com.xiaoniu.lib_keleim.utils.*
import java.lang.Byte

class Dispatcher :ReceiveMessageListener{
    var context: Context? = null
    var msgTypes = HashMap<Int,Class<*>>()

    val mNetworkModuleFactorys = hashMapOf<Schemes, INetworkModule>()
    val mInterceptors = hashMapOf<InterceptType, Interceptor>()
    var retryCount = 0
    var mReceiveMessageListener: ReceiveMessageListener? = null


    fun connect(context: Context, userInfo: UserEntity?) {
        this.context = context
        if (userInfo!=null && userInfo.customerId>0) {
            TextMessageUtils.sendUser = userInfo

            mNetworkModuleFactorys.values.forEach {
                it.connect(userInfo.do2vo())
                it.addOnReceiveMessageListener(this)
            }
        }else{
            TextMessageUtils.sendUser = null
        }
    }

    fun registerMsgType(msgType: HashMap<Int,Class<*>>) {
        msgTypes = msgType
    }

    fun joinRoom(roomId: String) {
        mNetworkModuleFactorys.values.forEach {
            it.joinRoom(roomId)
        }
    }

    fun quitRoom(roomId: String) {
        mNetworkModuleFactorys.values.forEach {
            it.quitRoom(roomId)
        }
        MessageFilterUtil.clear();
    }

    fun getConversations(schemes:Schemes,conversationType:ConversationType, targetId:String, callBack: ConversationListCallBack) {
        mNetworkModuleFactorys[schemes]?.getConversations(conversationType,targetId,callBack)
    }

    fun getMessages(schemes:Schemes, conversationType:ConversationType, targetId:String, channelId:String, option: HistoryMessageOption, callBack: MessageListCallBack) {
        mNetworkModuleFactorys[schemes]?.getMessages(conversationType,targetId,channelId,callBack)
    }

    fun getUnreadCount(schemes:Schemes,conversationType:ConversationType, targetId:String, channelId:String, callBack: MessageCountCallBack) {
        mNetworkModuleFactorys[schemes]?.getUnreadCount(conversationType,targetId,channelId,callBack)
    }

    fun sendMessage(message: BaseMessage) {
        MessageUtils.setBaseInfo(message)

        InterceptorUtil.callSendInterceptor(mInterceptors, InterceptType.SEND,message)

        MessageDao.getInstance().updateMessageEntity(message)

        val wrapperMessage = WrapperMessage()
        wrapperMessage.message = message

        InterceptorUtil.callSerializationInterceptor(mInterceptors, InterceptType.SERIALIZATION,wrapperMessage)
        InterceptorUtil.callEncodeInterceptor(mInterceptors, InterceptType.ENCODE,wrapperMessage)

        val sendMessage = PreSendMessage(message.conversationType, message.targetId.toString(),wrapperMessage.messageRawData)

        val networkModule = getNetworkModule(message.uriScheme)
        networkModule.sendMessage(sendMessage)
    }



    fun insertMessage(message: BaseMessage) {
        MessageUtils.setBaseInfo(message)
        MessageDao.getInstance().updateMessageEntity(message)

        InterceptorUtil.callSendInterceptor(mInterceptors, InterceptType.SEND,message)

    }

    fun sendPrivateMessage(message: Any?) {

    }

    fun addNetworkModule(networkModuleFactory: INetworkModuleFactory): Dispatcher {
        networkModuleFactory.createNetworkModule().let {
            addOnReceiveMessageListener(this)
            mNetworkModuleFactorys[networkModuleFactory.supportedUriSchemes] = it
        }
        return this
    }

    fun addConverterFactory(converterFactory: IConverterFactory): Dispatcher {
        return this
    }

    fun addInterceptor(interceptor: Interceptor): Dispatcher {
        mInterceptors[interceptor.interceptType] = interceptor
        return this
    }

    fun retryOnConnectionFailure(retryOnConnectionFailure: Int): Dispatcher {
        retryCount = retryOnConnectionFailure
        return this
    }

    fun addOnReceiveMessageListener(listener: ReceiveMessageListener): Dispatcher {
        mReceiveMessageListener = listener
        return this
    }

    override fun onReceivedMessage(message: BaseMessage?) {
        message?.let {
            val wrapperMessage = WrapperMessage()
            wrapperMessage.message = it

            InterceptorUtil.callDecodeInterceptor(mInterceptors, InterceptType.DECODE,wrapperMessage)
            InterceptorUtil.callParseInterceptor(mInterceptors, InterceptType.PARES,wrapperMessage)
            InterceptorUtil.callReceiveInterceptor(mInterceptors, InterceptType.RECEIVE,wrapperMessage)
            mReceiveMessageListener?.onReceivedMessage(message)

            sendReceivedAckMessage(it)
        }

    }

    override fun onReceivedMessage(target: String?, message: String?) {

        val wrapperMessage = WrapperMessage()
        wrapperMessage.messageRawData = message
        InterceptorUtil.callDecodeInterceptor(mInterceptors, InterceptType.DECODE,wrapperMessage)
        InterceptorUtil.callParseInterceptor(mInterceptors, InterceptType.PARES,wrapperMessage)
        InterceptorUtil.callReceiveInterceptor(mInterceptors, InterceptType.RECEIVE,wrapperMessage)

        mReceiveMessageListener?.onReceivedMessage(target,message)
    }

    private fun sendReceivedAckMessage(receiveMessage: BaseMessage){
        //确认接收消息
        AckMessage.obtainReceived(receiveMessage.targetId.toString(),ConversationType.PRIVATE).let {
            val sendMessage = PreSendMessage(it.conversationType, receiveMessage.targetId.toString(),it.rawData)
            val networkModule = getNetworkModule(Schemes.WEB_SOCKET)
            networkModule.sendMessage(sendMessage)
        }
    }

    private fun sendReadAckMessage(receiveMessage: BaseMessage){
        //确认已读消息
        AckMessage.obtainRead(Byte.valueOf(1),receiveMessage.targetId.toString(),ConversationType.PRIVATE).let {
            val sendMessage = PreSendMessage(it.conversationType, receiveMessage.targetId.toString(),it.rawData)
            val networkModule = getNetworkModule(Schemes.WEB_SOCKET)
            networkModule.sendMessage(sendMessage)
        }
    }

    private fun getNetworkModule(uriScheme: Schemes): INetworkModule {
        if (mNetworkModuleFactorys[uriScheme]!=null) {
            return mNetworkModuleFactorys[uriScheme]!!
        }
        return mNetworkModuleFactorys[Schemes.RONGYUN]!!
    }
}